package ace.cmp.openfeign.security.oauth2.core.config;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.cloud.openfeign.security.OAuth2AccessTokenInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.security.oauth2.client.AuthorizedClientServiceOAuth2AuthorizedClientManager;
import org.springframework.security.oauth2.client.OAuth2AuthorizedClientManager;
import org.springframework.security.oauth2.client.OAuth2AuthorizedClientService;
import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository;
import org.springframework.util.function.SingletonSupplier;

/**
 * @author caspar
 * @date 2024/1/10 10:03 add oauth2 access token for contract
 */
public class FeignInternalServerOauth2SecurityConfig {
  public static SingletonSupplier<OAuth2AccessTokenInterceptor>
      oauth2AccessTokenInterceptorSingletonSupplier;
  public static SingletonSupplier<OAuth2AuthorizedClientManager>
      oauth2AuthorizedClientManagerSingletonSupplier;

  @ConditionalOnProperty(
      value = "ace.cloud.openfeign.oauth2.enable",
      matchIfMissing = true,
      havingValue = "true")
  @ConditionalOnMissingBean
  @Bean
  public OAuth2AccessTokenInterceptor defaultOauth2AccessTokenInterceptor(
      @Value("${spring.cloud.openfeign.oauth2.clientRegistrationId:}") String clientRegistrationId,
      OAuth2AuthorizedClientManager oauth2AuthorizedClientManager) {
    return getDefaultOauth2AccessTokenInterceptorInstance(
        clientRegistrationId, oauth2AuthorizedClientManager);
  }

  @ConditionalOnProperty(
      value = "ace.cloud.openfeign.oauth2.enable",
      matchIfMissing = true,
      havingValue = "true")
  @ConditionalOnMissingBean
  @Bean
  public OAuth2AuthorizedClientManager defaultOauth2AuthorizedClientManager(
      ClientRegistrationRepository clientRegistrationRepository,
      OAuth2AuthorizedClientService oauth2Authorizedclientservice) {
    return getDefaultOauth2AuthorizedClientManagerInstance(
        clientRegistrationRepository, oauth2Authorizedclientservice);
  }

  public static OAuth2AccessTokenInterceptor getDefaultOauth2AccessTokenInterceptorInstance(
      String clientRegistrationId, OAuth2AuthorizedClientManager oauth2AuthorizedClientManager) {
    if (oauth2AccessTokenInterceptorSingletonSupplier == null) {
      oauth2AccessTokenInterceptorSingletonSupplier =
          new SingletonSupplier<>(
              new OAuth2AccessTokenInterceptor(clientRegistrationId, oauth2AuthorizedClientManager),
              null);
    }
    return oauth2AccessTokenInterceptorSingletonSupplier.get();
  }

  public static OAuth2AuthorizedClientManager getDefaultOauth2AuthorizedClientManagerInstance(
      ClientRegistrationRepository clientRegistrationRepository,
      OAuth2AuthorizedClientService oauth2AuthorizedClientService) {
    if (oauth2AuthorizedClientManagerSingletonSupplier == null) {
      oauth2AuthorizedClientManagerSingletonSupplier =
          new SingletonSupplier<>(
              new AuthorizedClientServiceOAuth2AuthorizedClientManager(
                  clientRegistrationRepository, oauth2AuthorizedClientService),
              null);
    }
    return oauth2AuthorizedClientManagerSingletonSupplier.get();
  }
}
